#include "AD.h"

/*******************************************************************************
* 函数名         : SPI_Write
* 功能描述       : 使用SPI写入数据
* 输入           : dat - 要写入的数据
* 输出           : 无
*******************************************************************************/
static void SPI_Write(unsigned char dat)
{
    unsigned char i;
    CLK = 0;
    for(i = 0; i < 8; i++)
    {
        DIN = dat >> 7;      // 发送最高位
        dat <<= 1;
        CLK = 0;             // 时钟下降沿
        _nop_();
        CLK = 1;             // 时钟上升沿
        _nop_();
    }
}

/*******************************************************************************
* 函数名         : SPI_Read
* 功能描述       : 使用SPI读取数据
* 输入           : 无
* 输出           : 12位ADC值
*******************************************************************************/
static unsigned int SPI_Read(void)
{
    unsigned char i;
    unsigned int dat = 0;
    
    // 丢弃第一个无效位
    CLK = 1;
    _nop_();
    CLK = 0;
    _nop_();
    
    for(i = 0; i < 12; i++)      // 读取12位数据
    {
        CLK = 1;
        _nop_();
        CLK = 0;
        _nop_();
        dat <<= 1;
        if(DOUT)
            dat |= 1;
    }
    return dat;    
}

/*******************************************************************************
* 函数名         : ADC_Init
* 功能描述       : 初始化ADC
* 输入           : 无
* 输出           : 无
*******************************************************************************/
void ADC_Init(void)
{
    // 初始化控制引脚
    CS = 1;        // 默认不选中ADC
    CLK = 0;       // 时钟信号默认低电平
    DIN = 1;       // 数据线默认高电平
}

/*******************************************************************************
* 函数名         : ADC_Read
* 功能描述       : 读取指定通道的ADC值
* 输入           : ch - ADC通道号(0-7)
* 输出           : 12位ADC转换结果(0-4095)
* 说明           : 返回XPT2046的完整12位ADC值
*******************************************************************************/
// 滤波缓冲区大小
#define FILTER_SIZE 8

// 滤波缓冲区
static unsigned int filter_buf[FILTER_SIZE];
static unsigned char filter_index = 0;

/*******************************************************************************
* 函数名         : Filter_Value
* 功能描述       : 对ADC值进行滤波
* 输入           : value - 新的ADC值
* 输出           : 滤波后的ADC值
*******************************************************************************/
static unsigned int Filter_Value(unsigned int value)
{
    unsigned long sum = 0;
    unsigned char i;
    
    // 更新缓冲区
    filter_buf[filter_index] = value;
    filter_index = (filter_index + 1) & (FILTER_SIZE - 1);  // 循环更新索引
    
    // 计算平均值
    for(i = 0; i < FILTER_SIZE; i++)
    {
        sum += filter_buf[i];
    }
    
    return (unsigned int)(sum / FILTER_SIZE);
}

/*******************************************************************************
* 函数名         : ADC_Read
* 功能描述       : 读取指定通道的ADC值
* 输入           : ch - ADC通道号(0-7)
* 输出           : 12位ADC转换结果(0-4095)
* 说明           : 返回XPT2046的完整12位ADC值
*******************************************************************************/
unsigned int ADC_Read(unsigned char ch)
{
    unsigned int temp;
    unsigned char cmd;
    
    // 构造命令字节
    // 对于通道0（电位器输入）固定使用0x94命令
    // 0x94 = 1001 0100
    // 1    - 启动位
    // 000  - 选择通道0（AIN0）
    // 1    - 供电模式
    // 1    - 12位分辨率
    // 00   - 空闲位
    cmd = 0x94;    // 固定使用通道0
    
    CS = 0;                    // 片选有效
    SPI_Write(cmd);           // 发送命令
    
    // 等待转换完成
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    
    temp = SPI_Read();        // 读取12位ADC值
    CS = 1;                    // 片选无效
    
    // 对读取的值进行滤波
    return Filter_Value(temp);
}